package ru.ifmo.segal.algorithms;

import ru.ifmo.segal.Algorithm;
import ru.ifmo.segal.InitialConfig;

import java.util.ArrayList;
import java.util.List;

/**
 * @author avhaliullin
 */
public class Implicit implements Algorithm {
    private final boolean backward;

    public Implicit(boolean backward) {
        this.backward = backward;
    }

    private Double safeGet(List<Double> list, int index) {
        return index < 0 || index >= list.size() ? 0 : list.get(index);
    }

    public List<Double> step(InitialConfig config, int stepNum, List<Double> prev) {
        double dx = config.getDistanceSegmentation().getStep();
        double dt = config.getTimeSegmentation().getStep();
        double u = config.getU();
        double kappa = config.getKappa();
        List<Double> a = new ArrayList<Double>();
        List<Double> b = new ArrayList<Double>();
        List<Double> c = new ArrayList<Double>();
        List<Double> f = new ArrayList<Double>();

        for (int i = 0; i < config.getDistanceSegmentation().getCount(); i++) {
            b.add((backward ? (0) : (u / dx)) - kappa / Math.pow(dx, 2));
            a.add((backward ? (-u / dx) : (0)) - kappa / Math.pow(dx, 2));
            c.add((backward ? (u / dx) : (-u / dx)) + 1 / dt + 2 * kappa / Math.pow(dx, 2));
            f.add(prev.get(i) / dt);
        }

        return Utils.thomas(a, b, c, f);    // paravozik thomas
    }
}
